#ifndef COMBINATIONS_H
#define COMBINATIONS_H

#include "cardtypes.h"
#include "CCard.h"
#include <map>
#include <vector>
#include <array>

using namespace std;

/*****************************************************************************/
/**                             class CCombination                          **/
/*****************************************************************************/

typedef struct tagIsRange
{
    bool isValid;
    CCard::ValueType endOfRange;
    //Length
    //endOfRange
} Range;

class CCardSet;
class CHand;
class CDeck;

class CCombination
{
public:
    CCombination() { }

    COMBINATION_TYPE calcCombinationType(const CHand& hand);
private:
    bool isPair();
    bool isTwoPairs();
    bool isTheeOfAKind();
    bool isFourOfAKind();
    bool isFullHouse();
    bool isSameSuite();
    bool isStraight();
    bool isFlush();
    bool isStraightFlush();
    bool isRoyalFlush();
    void getEqRanges(const CHand& hand);
    Range getRange(const CHand& hand);

    map< CCard::ValueType, int > mEqValues;
    map< CCard::SuitType, int >  mEqSuits;
    Range mRange;
};


/*****************************************************************************/
/**                       class CBestCombinationFinder                      **/
/*****************************************************************************/

class CBestCombinationFinder
{
public:
    CBestCombinationFinder() {}
    CHand findBestHand(CCardSet& cardSet);
    void operator () (vector<CCard>::iterator begin, vector<CCard>::iterator);
private:
    CHand* mpBestHand;
};

/*****************************************************************************/
/**                      class CBestCombinationFinder7                      **/
/*****************************************************************************/

//class CBestCombinationFinder7
//{
//public:
//    CBestCombinationFinder7() {}
//    CHand findBestHand(CCardSet& cardSet);
//private:
//
//};

/*****************************************************************************/
/**                     class CHoldemCombinationsFinder                     **/
/*****************************************************************************/

class CHoldemCombinationsFinder
{
public:
    CHoldemCombinationsFinder() {}
    void findAllHands(const CCardSet& hand, const CCardSet& table);
    void operator () (vector<CCard>::iterator begin, vector<CCard>::iterator);

    array<int, 7462> mMyHandsCount;
    array<CHand*, 7462 > mMyHands;

    array<int, 7462> mOppHandsCount;
    array<CHand*, 7462 > mOppHands;

    int mWin;
    int mLose;
    int mDraw;
private:
    CDeck* mpDeck;
    CCardSet* mpMyCardSet;
    CCardSet* mpOppCardSet;
    CBestCombinationFinder mBestFinder;

    class CFunctor
    {
    public:
        CFunctor(CHoldemCombinationsFinder& holdemCalc ): mHoldemCalc(holdemCalc) {}
        void operator () (vector<CCard>::iterator itBegin, vector<CCard>::iterator itEnd)
        {
            mHoldemCalc(itBegin, itEnd);
        };
        CHoldemCombinationsFinder& mHoldemCalc;
    };
};

/*****************************************************************************/
/**                                   Misc                                  **/
/*****************************************************************************/

string CombinationTypeToString(COMBINATION_TYPE comb);

unsigned int getCombinationStrength(COMBINATION_TYPE combination, const CHand& hand);

#endif // COMBINATIONS_H
